﻿using EWSEditor.Common;
using EWSEditor.Forms;
using Microsoft.Crm.Sdk.Messages;
using Microsoft.Xrm.Sdk;
using Microsoft.Xrm.Sdk.Client;
using Microsoft.Xrm.Sdk.Query;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Diagnostics;
using System.Drawing;
using System.Linq;
using System.Net;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;

namespace EWSEditor.CRM.Forms
{
    public partial class SupportUserSignInForm : CrmServiceDialog
    {

        private static NetworkCredential _savedCreds;
        private static string _orgUrl;
        private EntityCollection _mailboxes;
        private ListViewColumnSorter _lvwColumnSorter;
        private BrowserForm _parentForm;
        

        public SupportUserSignInForm(bool HideBase, BrowserForm browserForm) : base(HideBase, browserForm)
        {
            InitializeComponent();
            CrmOrgMailboxCache.SupportMode = true;
            _parentForm = browserForm;
        }

        private void btnGetMailboxes_Click(object sender, EventArgs e)
        {
            try
            {
                listMailboxes.Items.Clear();
                listMailboxes.ListViewItemSorter = null;
                Cursor = Cursors.WaitCursor;
                btnGetMailboxes.Enabled = false;
                ValidateAndSetProperties();
                OrganizationServiceProxy orgProxy = CrmAuthInfoFactory.GetOrgProxy();
               
                _mailboxes = GetMailboxes(orgProxy);

                if (_mailboxes.Entities.Count < 1)
                {
                    Cursor = Cursors.Default;
                    MessageBox.Show(this, "No active mailboxes found.", "Error", MessageBoxButtons.OK, MessageBoxIcon.Error);
                    btnGetMailboxes.Enabled = true;
                    return;
                }

                PopulateMailboxView();
                _lvwColumnSorter = new ListViewColumnSorter();
                listMailboxes.ListViewItemSorter = _lvwColumnSorter;
                btnGo.Enabled = true;
                SetSupportUserCache();
              
            }
            catch (Exception ex)
            {
                CrmAuthInfoFactory.ClearAuthProperties();
                Application.DoEvents();
                if (ex.InnerException != null)
                {
                    if (ex.InnerException.Message == "Authentication Failure")
                    {
                        MessageBox.Show("Dynamics 365 Authentication Failed. Please check your credentials.");
                        return;
                    }
                }
                if (!string.IsNullOrEmpty(ex.Message) && ex.Message == "Access is denied.")
                {
                    MessageBox.Show("Dynamics 365 Authentication Failed. Please check your credentials.");
                    return;
                }
                CrmClientException.ShowException(ex);
                return;
            }
            finally
            {
                Cursor = System.Windows.Forms.Cursors.Default;
                btnGetMailboxes.Enabled = true;
            }
        }

        private void SetSupportUserCache()
        {
            _savedCreds = new NetworkCredential(txtbxUsername.Text, txtbxPassword.Text);
            _orgUrl = txtbxOrgUrl.Text;
        }

        private void PopulateMailboxView()
        {
            foreach(Entity mailbox in _mailboxes.Entities)
            {
                ListViewItem lvitem = new ListViewItem();
                lvitem.Tag = mailbox;

                if (mailbox.Attributes.Contains("name"))
                {
                    lvitem.Text = (string)mailbox["name"];
                }
                else
                {
                    lvitem.Text = "";
                }

                TestStatus incomingStatus = ((TestStatus)((OptionSetValue)mailbox["incomingemailstatus"]).Value);
                TestStatus outgoingStatus = ((TestStatus)((OptionSetValue)mailbox["outgoingemailstatus"]).Value);
                TestStatus actStatus = ((TestStatus)((OptionSetValue)mailbox["actstatus"]).Value);

                lvitem.SubItems.Add((string)mailbox["emailaddress"]);
                lvitem.SubItems.Add(incomingStatus.ToString());
                lvitem.SubItems.Add(outgoingStatus.ToString());
                lvitem.SubItems.Add(actStatus.ToString());
                listMailboxes.Items.Add(lvitem);
            }
        }

        private EntityCollection GetMailboxes(OrganizationServiceProxy orgProxy)
        {
            string fetchxml = GetFetchXml();
            FetchXmlToQueryExpressionResponse queryExpression = SharedUtilities.ConvertFetchToQuery(fetchxml, orgProxy);
            EntityCollection mailboxes = SharedUtilities.ExecuteQueryWithPaging(queryExpression.Query, orgProxy);
            return mailboxes;
        }

        private string GetFetchXml()
        {
            string fetchxml = @"<fetch version='1.0' output-format='xml-platform' mapping='logical' distinct='false'>
  <entity name='mailbox'>
    <attribute name='name' />
    <attribute name='regardingobjectid' />
    <attribute name='ownerid' />
    <attribute name='emailaddress' />
    <attribute name='mailboxid' />
    <attribute name='outgoingemailstatus' />
    <attribute name='incomingemailstatus' />
    <attribute name='actstatus' />
    <order attribute='name' descending='false' />
    <filter type='and'>
      <condition attribute='statecode' operator='eq' value='0' />
      <condition attribute='emailaddress' operator='not-null' />
    </filter>
  </entity>
</fetch>";

            return fetchxml;
        }

        private void btnGo_Click(object sender, EventArgs e)
        {
            try
            {
                Entity mailbox;
                Cursor = Cursors.WaitCursor;

                //If the user has specified an address, use it to set the mailbox and cache data.
                if (txtTargetMailbox.Text.Contains("@") && (txtTargetMailbox.Text.Contains(".")))
                {
                    ValidateAndSetProperties();
                    mailbox = base.ValidateAndSetTargetMailbox(CrmAuthInfoFactory.GetOrgProxy(), txtTargetMailbox.Text);
                    SetSupportUserCache();
                }
                else if ((txtMailboxId.Text.Length == 36) && (txtMailboxId.Text.Contains("-")))
                {
                    ValidateAndSetProperties();
                    mailbox = GetMailboxById(txtMailboxId.Text);
                    SetSupportUserCache();
                }
                else
                {
                    {

                        if (listMailboxes.SelectedItems.Count == 0)
                        {
                            MessageBox.Show("Please select a mailbox");
                            return;
                        }

                        mailbox = (Entity)listMailboxes.SelectedItems[0].Tag;
                        ValidateAndSetTargetMailbox(CrmAuthInfoFactory.GetOrgProxy(), null);
                    }
                }

                DetermineUserOrQueueMailbox(mailbox, CrmAuthInfoFactory.GetOrgProxy());
                SetOrgMailboxCache(mailbox, CrmAuthInfoFactory.GetOrgProxy());
                CrmOrgMailboxCache.SupportMode = true;
                CRMMenuOptionsHelper.EnableCRMMenuOptions(_parentForm.mnuMain, CRMMenuMode.SupportMode);
                Cursor = Cursors.Default;
                DialogResult = DialogResult.OK;

            }
            catch (Exception ex)
            {
                Cursor = Cursors.Default;
                MessageBox.Show(this, ex.StackTrace, ex.Message, MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
        }

        private Entity GetMailboxById(string text)
        {
            Entity mailbox = CrmAuthInfoFactory.GetOrgProxy().Retrieve("mailbox", new Guid(text), new ColumnSet() { AllColumns = true});
            return mailbox;
        }

        private void ValidateAndSetProperties()
        {
            ValidateInputs();
            CrmAuthInfoFactory.ClearAuthProperties();
            CrmAuthInfoFactory.SetProperties(txtbxUsername.Text, txtbxPassword.Text, txtbxOrgUrl.Text, null, null, null);
        }

        protected override Entity ValidateAndSetTargetMailbox(OrganizationServiceProxy orgProxy, string emailAddress = null)
        {
            Entity mailbox = (Entity)listMailboxes.SelectedItems[0].Tag;
            CrmOrgMailboxCache.TargetMailbox = mailbox;
            return mailbox;
        }

        public static DialogResult ShowDialog(bool custom, BrowserForm browserForm)
        {
            SupportUserSignInForm dialog = new SupportUserSignInForm(true, browserForm);
            DialogResult res = dialog.ShowDialog();
            return res;
        }

        protected override void ValidateInputs()
        {
            //Validate Inputs
            if (txtbxOrgUrl.Text == "https://<org>.crm.dynamics.com")
            {
                throw new Exception("Please supply a valid Dynamics 365 Organization Service URL.");
            }
            if (string.IsNullOrEmpty(txtbxUsername.Text))
            {
                throw new Exception("Please supply a valid Dynamics 365 Username.");
            }
            if (string.IsNullOrEmpty(txtbxPassword.Text))
            {
                throw new Exception("Please supply a valid Dynamics 365 Password.");
            }
        }

        private void listMailboxes_ColumnClick(object sender, ColumnClickEventArgs e)
        {
            // Determine if clicked column is already the column that is being sorted.
            if (e.Column == _lvwColumnSorter.SortColumn)
            {
                // Reverse the current sort direction for this column.
                if (_lvwColumnSorter.Order == SortOrder.Ascending)
                {
                    _lvwColumnSorter.Order = SortOrder.Descending;
                }
                else
                {
                    _lvwColumnSorter.Order = SortOrder.Ascending;
                }
            }
            else
            {
                // Set the column number that is to be sorted; default to ascending.
                _lvwColumnSorter.SortColumn = e.Column;
                _lvwColumnSorter.Order = SortOrder.Ascending;
            }

            // Perform the sort with these new sort options.
            listMailboxes.Sort();
        }

        private void linkLabel1_LinkClicked(object sender, LinkLabelLinkClickedEventArgs e)
        {
            string command = "mailto:debrau@microsoft.com?subject=EWSEditor For Dynamics 365 Feedback";
            Process.Start(command);
        }

        private void SupportUserSignInForm_Load(object sender, EventArgs e)
        {
            if (_savedCreds != null)
            {
                txtbxUsername.Text = _savedCreds.UserName;
                txtbxPassword.Text = _savedCreds.Password;
                txtbxOrgUrl.Text = _orgUrl;
                btnGetMailboxes.Text = "Refresh Mailboxes";
            }
            else
            {
                txtbxUsername.Text = System.DirectoryServices.AccountManagement.UserPrincipal.Current.EmailAddress;
                //System.Security.Principal.WindowsIdentity.GetCurrent().Name
            }
        }

        private void txtTargetMailbox_TextChanged(object sender, EventArgs e)
        {
            if (txtTargetMailbox.Text.Contains("@") && (txtTargetMailbox.Text.Contains(".")))
            {
                btnGetMailboxes.Enabled = false;
                btnGo.Enabled = true;
                grpMailboxes.Enabled = false;
                txtMailboxId.Enabled = false;
            }
            else if ((string.IsNullOrEmpty(txtTargetMailbox.Text)) && (string.IsNullOrEmpty(txtMailboxId.Text)) && (listMailboxes.Items.Count > 0))
            {
                btnGetMailboxes.Enabled = true;
                btnGo.Enabled = true;
                grpMailboxes.Enabled = true;
                txtMailboxId.Enabled = true;
            }
            else
            {
                btnGetMailboxes.Enabled = true;
                btnGo.Enabled = false;
                grpMailboxes.Enabled = true;
                txtMailboxId.Enabled = true;
            }
        }

        private void txtMailboxId_TextChanged(object sender, EventArgs e)
        {
            if ((txtMailboxId.Text.Length == 36 ) && (txtMailboxId.Text.Contains("-")))
            {
                btnGetMailboxes.Enabled = false;
                btnGo.Enabled = true;
                grpMailboxes.Enabled = false;
                txtTargetMailbox.Enabled = false;
            }
            else if ((string.IsNullOrEmpty(txtTargetMailbox.Text)) && (string.IsNullOrEmpty(txtMailboxId.Text)) && (listMailboxes.Items.Count > 0))
            {
                btnGetMailboxes.Enabled = true;
                btnGo.Enabled = true;
                grpMailboxes.Enabled = true;
                txtTargetMailbox.Enabled = true;
            }
            else
            {
                btnGetMailboxes.Enabled = true;
                btnGo.Enabled = false;
                grpMailboxes.Enabled = true;
                txtTargetMailbox.Enabled = true;
            }
        }
    }
}
